#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
    Copyright (c) 2007, Jiří Procházka
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    The author can be reached via e-mail to Pro.J@seznam.cz
"""

#COMMENT INFO: comments "#pyvcsgui" are for a release script to remove the lines with them for console-only release

import getopt, sys, os, pyvcsCore, ConfigParser, traceback
import wxPyvcs #pyvcsgui

#reading configuration
conffile = open(os.path.join(os.path.dirname(sys.argv[0]),'pyvcs.conf'), 'r')        #open pyvcs file and read to ConfigParser from it
conf = ConfigParser.ConfigParser()
conf.readfp(conffile)
conffile.close()
usegui = int(conf.get('Main', 'usegui'))
diffapp = conf.get('Main', 'diffapp')

#help information
helpstring = """PYVCS 1.0 - (PYthonVersionControlSystem / PYthonVersionControlSimple)
Pyvcs is used for simple version control of any files

USAGE (*nix):         python Pyvcs.py [OPTIONS]... [FILE]...
USAGE (Windows):      Pyvcs.py [OPTIONS]... [FILE]...

-h, --help            print this help
-l, --list=FILE/DIR   list version archives in the directory of FILE (use "-l ." for current directory)
-f, --file=FILE       print name and versions of the FILE version archive
-e, --extract=FILE    extract a version of the FILE version archive
-a, --add=FILE        add FILE to the version archive
-c, --create=FILE     make FILE version controlled - create version archive
-d, --diff=FILE       run a diff aplication (pyvcs.conf) for versions in the FILE archive
"""
helpstringgui = """-m, --menu=FILE       launch a menu GUI with buttons for all above options + configuration
-g, --gui             GUI swich on for above options, alone launches menu GUI with help and configuration
"""
helpstring = helpstring+helpstringgui #pyvcsgui


#FUNCTIONS FOR USER INTERACTION

def showerror():
    """function made to show errors"""
    perr = traceback.format_exc()
    if(usegui == 1):
        wxPyvcs.showerrwin(perr) #pyvcsgui
        print perr
    else:
        print perr

def prompt(question):
    """function for prompting user"""
    if(usegui == 1):
        return wxPyvcs.prompt(question) #pyvcsgui
        print 'prompt gui launched'
    else:
        return raw_input(question)
        
def filedialog(text, open = 1):
    """function for prompting user for files"""
    if(usegui == 1):
        return wxPyvcs.filedialog(text, open) #pyvcsgui
        print 'prompt gui launched'
    else:
        end = False
        while end != True:
            f = raw_input(text) 
            if os.access(f, os.F_OK) == True:
                if open == 1:
                    end = True
                else:
                    print 'error: this file already exists! retry:'
            else:
                if open != 1:
                    end = True
                else:
                    print 'error: specified file doesn\'t exist! retry:'            
        return f
        
def printinfo(info):
    """function printing information for user"""
    if(usegui == 1):
        wxPyvcs.printinfo(info) #pyvcsgui
        print 'printinfo gui launched'
    else:
        print info

#FUNCTIONS FOR GETTING THE NECESSARY INFO FROM USER AND LAUNCHING THE CORE
    
def create(a):
    """function for creating version controlled archive"""
    #if file from which to create doesn't exist or wasn't specified print error
    if os.access(a, os.F_OK) == False:
        printinfo('error: file from which to create version archive doesn\'t exist')
        return 0
    fname = os.path.split(os.path.abspath(a))[1]
    path = os.path.dirname(os.path.abspath(a))
    #check if the file isn't version controlled already
    if os.access(os.path.join(path,'.pyvcs',fname+'.pyvcs'), os.F_OK) == True or os.access(os.path.join(path,'.pyvcs',fname+'.tgz'), os.F_OK) == True:
        printinfo('error: this file is already version controlled!')
        return 0
    #prompt to get notes for the initial version
    notes = prompt('enter notes for this version: ')
    pyvcsCore.newarch(a, notes)
    
def add(a):
    """function for adding a new version to a version controlled archive"""
    #run consistency check
    consist(a)
    #does the file for which to add version exist? 
    if os.access(os.path.abspath(a), os.F_OK) == False:
        printinfo('error: file to add not found!')
        return 0
    #prompt to get notes for the version
    notes = prompt('enter notes for this version: ')
    pyvcsCore.addver(a, notes)

def extract(a):
    """function for extracting a new version from a version controlled archive"""
    #run consistency check
    consist(a)
    #prompt for version to extract
    ver = prompt('enter version to extract (for example "42"): ')
    #get path of the target - file to be extracted
    target = filedialog('filename (path) where to extract: ', 0)
    pyvcsCore.expver(a, target, ver)
    
def lista(a):
    """function for listing versions in a version controlled archive"""
    fname = os.path.split(os.path.abspath(a))[1]
    path = os.path.dirname(os.path.abspath(a))
    #run consistency check
    consist(a)
    #open the archive info file and read it
    file1 = open(os.path.join(path,'.pyvcs',fname+'.pyvcs'), 'r')
    file1c = ConfigParser.ConfigParser()
    file1c.readfp(file1)
    file1.close()
    #compose the info string
    info = fname+'\n\n'
    for verid in file1c.sections():
        if str(verid)[0] in set(['0','1','2','3','4','5','6','7','8','9']):
            info = info+'version '+file1c.get(str(verid), 'version')+'; created '+file1c.get(str(verid), 'date')+'; notes:\n'
            info = info+file1c.get(str(verid), 'notes')+'\n\n'
    #print the info
    printinfo(info)

def dira(a):
    """function for listing version controlled archives in directory"""
    #if the path isn't a directory then get the directory of the file
    if os.path.isdir(os.path.abspath(a)) == True:
        path = os.path.abspath(a)
    else:
        path = os.path.dirname(os.path.abspath(a))
    #are there any version archives?
    if os.access(os.path.join(path,'.pyvcs/'), os.F_OK) == False:
        printinfo('error: no version controlled files found')
        return 0
    #get files in pyvcs directory
    dir = os.listdir('.pyvcs/')
    #compose the info, with every version archive info file
    info = ''
    for i in dir:
        x = str(i).split('.')
        if x[-1] == 'pyvcs':
            info = info+'.'.join(x[:-1])+'\n'
    printinfo(info)
    
def diff(a):
    """function for launching a diff application with different versions of the archive"""
    fname = os.path.split(os.path.abspath(a))[1]
    path = os.path.dirname(os.path.abspath(a))
    #run consistency check
    consist(a)
    #get version for which to run diff
    ver1 = prompt('enter 1st version to diff with (for example "42"): ')
    ver2 = prompt('enter 2nd version to diff with (for example "41"): ')
    pyvcsCore.diff(a, diffapp, ver1, ver2)

def consist(a):
    """check if the archive exists, and if versions in the info file match the archive"""
    #parsing a
    fname = os.path.split(os.path.abspath(a))[1]
    fdir = os.path.dirname(os.path.abspath(a))
    #do all files and directories exist?
    if os.access(os.path.join(fdir,'.pyvcs'), os.F_OK) == False:
        printinfo('the .pyvcs directory containing archives doesn\'t exist')
        return 0
    if os.access(os.path.join(fdir,'.pyvcs',fname+'.pyvcs'), os.F_OK) == False or os.access(os.path.join(fdir,'.pyvcs',fname+'.tgz'), os.F_OK) == False:
        printinfo('error: the version archive not found!')
        return 0
    pyvcsCore.consist(a)

#SPECIAL FUNCTIONS

def main():
    """main function"""
    #using getopt to parse command-line options and arguments
    opts, args = getopt.getopt(sys.argv[1:], "ghc:a:e:f:l:m:d:", ["gui", "help", "create=", "add=", "extract=", "file=", "list=", "menu=", "diff="])
    #if no options specified, print help information and exit
    action = 'h'
    a = ''
    #parsing options and launching appropriate functions
    for o, a in opts:
        if o in ('-g', "--gui"): #pyvcsgui
            global usegui #pyvcsgui
            usegui = 1 #pyvcsgui
            if len(opts) == 1: #pyvcsgui #when -g is the only option show main menu
                menu() #pyvcsgui
        if o in ("-h", "--help"):
            action = 'h'
        if o in ("-c", "--create"):
            action = 'c'
        if o in ("-a", "--add"):
            action = 'a'
        if o in ("-e", "--extract"):
            action = 'e'
        if o in ("-f", "--file"):
            action = 'f'
        if o in ("-l", "--list"):
            action = 'l'
        if o in ("-m", "--menu"):
            action = 'm'
        if o in ("-d", "--diff"):
            action = 'd'
    runaction(action, a)

def menu(file = False):
    """function for launching gui menu"""
    action = ''
    #launch the menu and get the action-to-be-run code in return
    action = wxPyvcs.genmenu(file) #pyvcsgui
    print 'menu gui launched'
    #make sure we are in gui mode
    global usegui #pyvcsgui
    usegui = 1 #pyvcsgui
    runaction(action, file)
    
def runaction(action, file=''):
    """function for running different actions"""
    if action == 'c':
        create(file)
    if action == 'a':
        add(file)
    if action == 'e':
        extract(file)
    if action == 'f':
        lista(file)
    if action == 'l':
        dira(file)
    if action == 'd':
        diff(file)
    if action == 'm':
        menu(file)
    if action == 'h':
        printinfo(helpstring)
    if action == 'x':
        setconf(wxPyvcs.conf()) #pyvcsgui
        print 'launching configuration gui'
    
def setconf(confdict):
    """function for writing to configuration file"""
    #write the info from the dictionary input to the configuration object
    cnf = ConfigParser.ConfigParser()
    cnf.add_section('Main')
    for i in confdict.keys():
        cnf.set('Main', i, confdict[i])
    #write the configuration to the pyvcs.conf
    conffile = open(os.path.join(os.path.dirname(sys.argv[0]),'pyvcs.conf'), 'w')
    cnf.write(conffile)
    conffile.close()

#RUN

#run the program if its not loaded as module
if __name__ == "__main__":
    try:
        main()
    except:
        showerror()
